package biz

import (
	"context"
	"github.com/duke-git/lancet/v2/slice"
	"github.com/go-kratos/kratos/v2/log"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/trace"
	amount_v1 "gorm_transaction/api/Amount1Server/v1"
)

/*
-- 创建有 数组 类型字段的表
create table whw_ck_test_db.staff (
      sid UUID comment '员工id',
      s_name String comment '员工姓名',
      age UInt8 comment '员工年龄',
      hobbies Array(String) DEFAULT [] comment '爱好'
) ENGINE = MergeTree ORDER BY (sid,s_name) PRIMARY KEY (sid);

-- 往有嵌套类型字段的表中插入数据
insert into whw_ck_test_db.staff VALUES (generateUUIDv4(), 'whw', 22,['football','basketball']),
                                        (generateUUIDv4(), 'naruto', 24,['football']);
*/

const (
	StaffTableName = "staff"
)

type Staff struct {
	SID     string   `gorm:"column:sid;type:uuid;comment:员工id" json:"sid"`
	SName   string   `gorm:"column:s_name;type:string;comment:员工姓名" json:"s_name"`
	Age     uint8    `gorm:"column:age;type:uint8;comment:员工年龄" json:"age"`
	Hobbies []string `gorm:"column:hobbies;type:string[]" json:"hobbies"` // ClickHouse Array 类型
}

type StaffBizStruct struct {
	staffRepo StaffBizInterface
	logger    log.Logger
}

func NewStaffBiz(staffRepo StaffBizInterface, logger log.Logger) *StaffBizStruct {
	return &StaffBizStruct{
		staffRepo: staffRepo,
		logger:    logger,
	}
}

type StaffBizInterface interface {
	GetStaffsBySName(ctx context.Context, sName string) ([]*Staff, error)
	CreateStaffs(ctx context.Context, staffs []*Staff) error
}

func (s *StaffBizStruct) GetStaffsBySName(ctx context.Context, req *amount_v1.GetStaffsBySNameReq) (ret *amount_v1.GetStaffsBySNameReply, errRet error) {
	ctx, span := otel.Tracer("BIZ").Start(ctx, "GetStaffsBySNameBiz", trace.WithSpanKind(trace.SpanKindInternal))
	defer span.End()

	models, errModels := s.staffRepo.GetStaffsBySName(ctx, req.GetSName())
	if errModels != nil {
		return nil, errModels
	}

	// 转结构
	retStaffs := make([]*amount_v1.Staff, 0)
	retStaffs = slice.Map(models, func(index int, item *Staff) *amount_v1.Staff {
		return &amount_v1.Staff{
			Sid:     item.SID,
			SName:   item.SName,
			Age:     uint32(item.Age),
			Hobbies: item.Hobbies,
		}
	})

	//fmt.Println("retStaff:>>>>> ", gconv.String(retStaffs))

	ret = &amount_v1.GetStaffsBySNameReply{}
	ret.Staffs = retStaffs

	return ret, nil
}

func (s *StaffBizStruct) CreateStaffs(ctx context.Context, req *amount_v1.CreateStaffsReq) (ret *amount_v1.Empty, errRet error) {
	ctx, span := otel.Tracer("BIZ").Start(ctx, "CreateStaffsBiz", trace.WithSpanKind(trace.SpanKindInternal))
	defer span.End()

	createStaffs := make([]*Staff, 0)
	if req.GetStaffs() == nil || len(req.GetStaffs()) < 1 {
		return &amount_v1.Empty{}, nil
	}

	for _, item := range req.GetStaffs() {
		currStaff := Staff{
			SID:     item.GetSid(),
			SName:   item.GetSName(),
			Age:     uint8(item.GetAge()),
			Hobbies: item.GetHobbies(),
		}
		createStaffs = append(createStaffs, &currStaff)
	}

	errRet = s.staffRepo.CreateStaffs(ctx, createStaffs)

	return &amount_v1.Empty{}, errRet
}
